﻿using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Toolkit.Lib.CodeModels;
using Toolkit.Lib.Services;

namespace iOSClub.Toolkit.WindowApp.ViewModels.Pages;

public class DocumentPageModel : PageModelBase
{
    private string _softName = "";

    public string SoftName
    {
        get => _softName;
        set => SetField(ref _softName, value);
    }

    private string _company = "";

    public string Company
    {
        get => _company;
        set => SetField(ref _company, value);
    }

    private string _docPath = "";

    public string DocPath
    {
        get => _docPath;
        set => SetField(ref _docPath, value);
    }

    public ObservableCollection<MemberModel> Members { get; set; } = new();

    private GitIgnore Ignore { get; set; } = new(System.Array.Empty<string>());

    public ObservableCollection<SourceFileModel> Files { get; set; } = new();

    public async void AddFile()
    {
        var result =
            await new Window().StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions()
                {
                    AllowMultiple = true
                }
            );
        if (result.Count == 0) return;
        foreach (var storageFile in result)
        {
            if (Ignore.IsIgnored(storageFile.Path.LocalPath)) continue;
            var file = new SourceFileModel(storageFile.Path.LocalPath);
            if (file.IsCodeFile)
                Files.Add(file);
        }
    }

    public async void AddDocPath()
    {
        var result = await new Window().StorageProvider
            .OpenFolderPickerAsync(new FolderPickerOpenOptions());
        if (result.Count == 0) return;
        if (!Directory.Exists(result[0].Path.LocalPath)) return;
        DocPath = result[0].Path.LocalPath;
    }
    
    public async void AddDir()
    {
        var result = await new Window().StorageProvider
            .OpenFolderPickerAsync(new FolderPickerOpenOptions());
        if (result.Count == 0) return;
        if (!Directory.Exists(result[0].Path.LocalPath)) return;
        SearchAndAddCodeFileFromPath(new DirectoryInfo(result[0].Path.LocalPath));
    }

    private void SearchAndAddCodeFileFromPath(DirectoryInfo dir)
    {
        foreach (var info in dir.EnumerateFileSystemInfos())
        {
            if (Ignore.IsIgnored(info.FullName)) continue;
            switch (info)
            {
                case DirectoryInfo directoryInfo:
                {
                    SearchAndAddCodeFileFromPath(directoryInfo);
                    break;
                }
                case FileInfo fileInfo:
                {
                    var a = new SourceFileModel(fileInfo.FullName);
                    if (a.IsCodeFile) Files.Add(a);
                    break;
                }
            }
        }
    }

    public async void AddIg()
    {
        var a = await new Window().StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions()
            {
                AllowMultiple = false,
            }
        );
        if (a.Count == 0) return;
        var result = a[0];
        var reader = new StreamReader(await result.OpenReadAsync());
        var s = await reader.ReadToEndAsync();
        reader.Dispose();
        Ignore = new GitIgnore(s.Split("\n"));
    }

    public async Task<bool> Done()
    {
        if (Files.Count == 0 || Members.Count == 0 || string.IsNullOrEmpty(DocPath) ||
            string.IsNullOrEmpty(SoftName) || string.IsNullOrEmpty(Company))
            return false;

        //生成代码文件
        var path = Path.Combine(DocPath, $"程序-{SoftName}.docx");
        if (File.Exists(path)) File.Delete(path);
        var service = new WordDocumentService(path);
        // 同步方法，源代码有序，但性能较差
        foreach (var item in Files)
        {
            var encoding = Encoding.UTF8;
            // 部分IDE对cpp文件按照gbk编码
            if (item.Language == "C++") encoding = Encoding.GetEncoding("GB2312");

            using var reader = new StreamReader(item.FilePath, encoding);

            while (await reader.ReadLineAsync() is { } line)
            {
                if (string.IsNullOrEmpty(line)) continue;
                while (line.StartsWith(' '))
                    line = line.TrimStart(' ');
                while (line.StartsWith('\t'))
                    line = line.TrimStart('\t');
                service.AppendText(line);
            }
        }

        service.Save(SoftName, Company);
        service.Dispose();

        //生成合同
        var contract = new WordDocumentService(Path.Combine(DocPath, "合同.docx"));
        contract.BuildAndSaveContract(Members.ToList(), SoftName);
        contract.Dispose();
        return true;
    }
}